package com.springboot.tiki.service;

import com.springboot.tiki.minio.MinioConfig;
import io.minio.*;
import io.minio.http.Method;
import io.minio.messages.Bucket;
import io.minio.messages.Item;
import org.apache.tomcat.util.http.fileupload.IOUtils;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.time.LocalDate;
import java.util.List;

/**
 * @ClassName BucketService
 * @Description:
 * @author: kuaiqing
 * @CreateDate: 2025/10/22 14:10
 * @Version: 1.0
 */
@Service
public class BucketService {


    @Resource
    private MinioClient minioClient;
    @Resource
    private MinioConfig minioConfig;


    // 创建桶
    public void createBucket(String bucketName) {

        try {
            // 1.判断桶是不是已经存在
            if (minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build())) {
                throw new RuntimeException(String.format("桶【%s】已经存在", bucketName));
            }
            // 2.创建桶
            minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    // 删除桶
    public void deleteBucket(String bucketName) {
        try {
            // 1.判断桶是不是存在
            if (!minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build())) {
                throw new RuntimeException(String.format("桶【%s】不存在", bucketName));
            }
            minioClient.removeBucket(RemoveBucketArgs.builder().bucket(bucketName).build());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

    }

    // 查询所有桶
    public void listBucket() {
        try {
            List<Bucket> buckets = minioClient.listBuckets();
            for (Bucket bucket : buckets) {
                // 名称和创建时间
                System.out.println(bucket.name() + " " + bucket.creationDate());
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    // 上传文件
    public String putObject(MultipartFile file, String bucketName) {
        try {
            // 1.判断桶是不是存在
            if (!minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build())) {
                // 2.创建桶
                minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
            }
            // 时间
            LocalDate now = LocalDate.now();
            // 增加文件层级 时间+文件名
            String objectName = now.getYear() + "" + now.getMonthValue() + now.getDayOfMonth() + "/" + file.getOriginalFilename();

            ObjectWriteResponse objectWriteResponse = minioClient.putObject(
                    PutObjectArgs.builder()
                            .bucket(bucketName)
                            .object(objectName)
                            .stream(file.getInputStream(), file.getSize(), -1)
                            .contentType(file.getContentType())
                            .build()

            );
            return minioConfig.getEndpoint() + "/" + objectWriteResponse.bucket() + "/" + objectName;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    // 判断指定桶的文件是否存在
    public boolean statObjectExists(String bucketName, String objectName) {
        try {

            StatObjectResponse statObjectResponse = minioClient.statObject(
                    StatObjectArgs.builder()
                            .bucket(bucketName)
                            .object(objectName)
                            .build()
            );
            return true;
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
        return false;
    }
    // 生成可访问的url地址链接
    /**
     * 如果设置有效期时间
     * 最小是1s 最大支持到7天
     */
    public String getPresignedObjectUrl(String bucketName, String objectName) {
        try {
            if (!statObjectExists(bucketName, objectName)) {
                throw new RuntimeException(String.format("文件【%s】不存在", objectName));
            }
            GetPresignedObjectUrlArgs getPresignedObjectUrlArgs = GetPresignedObjectUrlArgs.builder()
                    .bucket(bucketName)
                    .object(objectName)
                    // seconds
                    .expiry(2)
                    .method(Method.GET)
                    .build();
            return minioClient.getPresignedObjectUrl(getPresignedObjectUrlArgs);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    // 下载文件
    public void getObject(String bucketName, String objectName, HttpServletResponse response) {
        try (InputStream stream = minioClient.getObject(
                GetObjectArgs.builder()
                        .bucket(bucketName)
                        .object(objectName)
                        .build())) {

            // 设置响应头
            response.setContentType("application/octet-stream");
            response.setHeader("Content-Disposition",
                    "attachment; filename=\"" + objectName + "\"");

            // 将文件流写入响应输出流
            IOUtils.copy(stream, response.getOutputStream());
            response.flushBuffer();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    // 获取指定桶所有的文件
    public void listObjects(String bucketName) {
        try {
            // 1.判断桶是不是存在
            if (!minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build())) {
                throw new RuntimeException(String.format("桶【%s】不存在", bucketName));
            }
            // 递归列出所有对象
            listObjectsRecursive(bucketName, "");
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    // 递归方法
    private void listObjectsRecursive(String bucketName, String prefix) {
        try {
            Iterable<Result<Item>> results = minioClient.listObjects(
                    ListObjectsArgs.builder()
                            .bucket(bucketName)
                            // 设置前缀
                            .prefix(prefix)
                            // 递归查询
                            .recursive(true)
                            .build()
            );

            for (Result<Item> result : results) {
                Item item = result.get();
                System.out.println("文件: " + item.objectName() + "   是否是目录: " + (item.isDir() ? "是" : "不是") + " 最终时间: " + item.lastModified() + " (大小: " + item.size() + " bytes)");
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    // 删除桶中的文件
    public void removeObject(String bucketName, String objectName) {
        try {
            // 1.判断桶是不是存在
            if (!minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build())) {
                throw new RuntimeException(String.format("桶【%s】不存在", bucketName));
            }
            // 2.判断文件是否存在
            if (!statObjectExists(bucketName, objectName)) {
                throw new RuntimeException(String.format("文件【%s】不存在", objectName));
            }
            minioClient.removeObject(
                    RemoveObjectArgs.builder()
                            .bucket(bucketName)
                            .object(objectName)
                            .build()
            );
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}

